package com.zhengke.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import com.zhengke.common.dao.CommonDao;
import com.zhengke.pojo.SysUser;
import com.zhengke.pojo.TvUser;

@Component
public class LoginServiceImpl implements LoginService{
    
	@Autowired
	private CommonDao dao;	
	
	@Autowired
	RedisTemplate<String, String> redisTemplate;
	@Resource(name="redisTemplate")
	ValueOperations<String, String> string;
	
	@Override
	public SysUser querySysUser(String loginName)throws Exception {
		SysUser su = (SysUser)dao.findForObject("sysUserMapper.selectByLoginName", loginName);
		return su;
	}
	
	@Override
	public int updateSysUser(SysUser su) throws Exception {
		int rst  = dao.update("sysUserMapper.updateByPrimaryKeySelective", su);
		return rst;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Object> queryMenu() throws Exception {
		List<Object> rtnList = new ArrayList<Object>();
		List<Map<String, Object>> lev1 = (List<Map<String, Object>>) dao.findForList("loginMapper.queryMenu", 1);
		List<Map<String, Object>> lev2 = (List<Map<String, Object>>) dao.findForList("loginMapper.queryMenu", 2);
		List<Map<String, Object>> lev3 = (List<Map<String, Object>>) dao.findForList("loginMapper.queryMenu", 3);
		for (Map<String, Object> map1 : lev1) {
			Map<String, Object> data1 = new HashMap<String, Object>();
			data1.put("id", map1.get("menu_id"));
			data1.put("iconfont", map1.get("icon"));
			data1.put("name", map1.get("menu_name"));
			data1.put("url", map1.get("url"));
			List<Object> list1 = new ArrayList<Object>();
			for (Map<String, Object> map2 : lev2) {
				if(map1.get("menu_id").equals(map2.get("pmenu_id"))){
					Map<String, Object> data2 = new HashMap<String, Object>();
					data2.put("id", map2.get("menu_id"));
					data2.put("iconfont", map2.get("icon"));
					data2.put("name", map2.get("menu_name"));
					data2.put("url", map2.get("url"));
					List<Object> list2 = new ArrayList<Object>();
					for (Map<String, Object> map3 : lev3) {
						if(map2.get("menu_id").equals(map3.get("pmenu_id"))){
							Map<String, Object> data3 = new HashMap<String, Object>();
							data3.put("id", map3.get("menu_id"));
							data3.put("iconfont", map3.get("icon"));
							data3.put("name", map3.get("menu_name"));
							data3.put("url", map3.get("url"));
							list2.add(data3);
						}
					}
					data2.put("sub", list2);
					list1.add(data2);
				}
			}
			data1.put("sub", list1);
			rtnList.add(data1);
		}
		
		return rtnList;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, String> queryPopedom(String userId,boolean isSuperAdmin) throws Exception {
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("userId", userId);
		List<Map<String, Object>> list = new ArrayList<>();
		
		if(isSuperAdmin){
			list = (List<Map<String, Object>>) dao.findForList("loginMapper.queryAllPopedom", map);
		}else{
			list = (List<Map<String, Object>>) dao.findForList("loginMapper.queryPopedom", map);
		}
		
		Map<String,String> rtnMap = new Hashtable<String,String>();
		for(Map<String,Object> sp : list){
			rtnMap.put(sp.get("item_code")+"", "1");
		}
		return rtnMap;
	}
	
	/**
	 * 	用户在2分钟内，仅允许输入密码错误5次，如果超过次数，限制其登录1小时
	 * 	
	 * 	登录错误次数key: user:loginCount:fail:用户名
	 * 	锁定限制登录key: user:loginTime:lock:用户名
	 * 
	 * 	执行登录时：
	 * 	1. 判断当前登录的用户是否被限制登录
	 * 		1.1 如果没有被限制登录
	 * 			（执行登录功能）
	 * 		2.如果登录成功
	 * 			2.1 登录成功 -->> 清楚输入密码错误次数信息
	 * 		3.如果登录失败
	 * 			3.1 记录登录错误次数
	 * 				（判断Redis中的登录次数key是否存在） user:loginCount:fail:用户名
	 * 				3.1.1 如果不存在
	 * 					是第一次登录 错误次数为1（user:loginCount:fail:用户名进行赋值，同时设置失效期）
	 * 				3.1.2 如果存在
	 * 					查询登录失败次数的key结果			
	 * 				if(结果<4)
	 * 					user:loginCount:fail:+1
	 * 				else{
	 * 					限制登录key存在，同时设置限制登录时间锁定1小时
	 * 					}
	 * 
	 * 	如果被限制，做出相应提示
	 */
	
	
	
	/**
	 *	 判断当前登录的用户是否被限制登录
	 *	查询当前key是否存在，如果存在，就被限制， 注意；需要给用户做提示：您当前的用户已被限制，还剩多长时间
	 *	如果不存在，就不被限制
	 */
	@Override
	public Map<String, Object> loginUserLock(String uname) {
		String key = TvUser.getLoginTimeLockKey(uname);
		Map<String, Object> map = new HashMap<String, Object>();
		if (redisTemplate.hasKey(key)) {
			long lockTime = redisTemplate.getExpire(key,TimeUnit.MINUTES);//以分钟为单位
			//如果存在
			map.put("flag", true);
			map.put("lockTime", lockTime);//还剩多长时间（小时为单位锁定，给用户返回分钟）
		}else {
			map.put("flag", false);
		}
		return map;
	}
	
	/**
	 * 	登录不成功相关操作
	 * 
	 */
	@Override
	public String loginValdate(String uname) {
		//记录登录错误次数key
		String key = TvUser.getLoginCountFailKey(uname);
		int num = 5;//登录错误的次数
		
		if (!redisTemplate.hasKey(key)) {//如果不存在
			//是第一次登录 错误次数为1（user:loginCount:fail:用户名进行赋值，同时设置失效期）
			//redisTemplate中在赋值时不能直接赋值并设置失效期（会设置失败）
			redisTemplate.opsForValue().set(key, "1");//先赋值
			redisTemplate.expire(key, 2, TimeUnit.MINUTES);//再设置失效期两分钟
			return "登录失败，在2分钟内还允许输入错误"+(num-1)+"次";
		}else {//如果存在
			//查询登录失败次数的key结果		
			long loginFailCount = Long.parseLong(redisTemplate.opsForValue().get(key));
			if (loginFailCount<(num-1)) {//代表如果当前登录失败次数<4 意思：还有资格继续进行登录
				//user:loginCount:fail:+1 登录次数+1
				redisTemplate.opsForValue().increment(key, 1);//对指定key增加指定数据
				long seconds = redisTemplate.getExpire(key,TimeUnit.SECONDS);//返回的是秒
				return uname+"登录失败，在"+seconds+"秒内还允许输入错误"+(num-loginFailCount-1)+"次";
			}else {//超过指定登录次数
				//限制登录key存在，同时设置限制登录时间锁定1小时
				redisTemplate.opsForValue().set(TvUser.getLoginTimeLockKey(uname), "1");
				redisTemplate.expire(TvUser.getLoginTimeLockKey(uname), 1, TimeUnit.HOURS);
				return "因登录失败次数超过限制"+num+"次，以对其限制登录1小时";
			}
		}
	}

	/*
	 *	清除登录失败次数的key 
	 */
	@Override
	public void clearLoginValdate(String uname) {
		String key = TvUser.getLoginCountFailKey(uname);
		redisTemplate.delete(key); 
	}



	
}
